﻿using System.Collections.Generic;
using System.IO;
using System.Text;

namespace OSMLib
{
    public class OsmBinWriter
    {
        private readonly Dictionary<int, IOsmWay> _ways;
        private readonly List<IOsmNode> _nodes;

        public OsmBinWriter(Dictionary<int, IOsmWay> ways, List<IOsmNode> nodes)
        {
            _ways = ways;
            _nodes = nodes;
        }

        public void WriteFile(string filename)
        {
            if (_ways.Count == 0)
            {
                return;
            }

            if (File.Exists(filename))
            {
                File.Delete(filename);
            }

            FileStream fs = File.Create(filename);

            var unicode = new UnicodeEncoding();

            using (var bw = new BinaryWriter(fs, unicode))
            {
                WriteWays(bw);
                WriteNodes(bw);
                bw.Flush();
                bw.Close();
            }
        }

        private void WriteWays(BinaryWriter stream)
        {
            stream.Write(_ways.Count);
            foreach (var wayID in _ways.Keys)
            {
                stream.Write(wayID);

                stream.Write(((OsmWay)_ways[wayID]).Nodes.Count);

                foreach (OsmNode node in ((OsmWay)_ways[wayID]).Nodes)
                {
                    stream.Write(node._wgs.Latitude);
                    stream.Write(node._wgs.Longitude);
                    stream.Write(node._tags.Count);
                    foreach (var kv in node._tags.Keys)
                    {
                        stream.Write(kv);
                        stream.Write(node._tags[kv]);
                    }
                }

                stream.Write(((OsmWay)_ways[wayID])._tags.Count);

                foreach (var tags in ((OsmWay)_ways[wayID])._tags)
                {
                    stream.Write(tags.Key);
                    stream.Write(tags.Value.Count);

                    foreach (var sz in tags.Value)
                    {
                        stream.Write(sz);
                    }
                }
            }
        }

        private void WriteNodes(BinaryWriter stream)
        {
            stream.Write(_nodes.Count);
            foreach (OsmNode node in _nodes)
            {
                stream.Write(node._wgs.Latitude);
                stream.Write(node._wgs.Longitude);
                stream.Write(node._tags.Count);
                foreach (var kv in node._tags.Keys)
                {
                    stream.Write(kv);
                    stream.Write(node._tags[kv]);
                }
            }
        }
    }
}
